package com.smartian.v2.utils;

import android.text.TextUtils;

import com.smartian.v2.TextPattern;
import com.smartian.v2.model.DateTimeNode;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by tianweitong on 2020/3/14.
 */

public class FestivalFilter {
    private SimpleDateFormat SDF = new SimpleDateFormat();
    private  final String QM_FESTIVAL = "清明节";
    static  FestivalFilter instance;

    private final String[][] COMMON_FESTEVL_WORDS = {
            {"3-8","妇女节","三八妇女节","38妇女","三八节"},
            {"3-7","女生节","37女神节","37女生节日","37女生节"},
            {"5-1","劳动节","51劳动节","五一劳动节","51劳动节"},
            {"5-4","青年节","54青年节","五四青年节"},
            {"6-1","儿童节","六一儿童节","61儿童节"},
            {"9-10","教师节"},
            {"10-1","国庆节","十一国庆节","11国庆节","十一国庆"},
            {"11-11","光棍节","双十一","双11"},
            {"12-12","双十二","双12"},
            {"7-1","建党节","七一建党节","71建党节","香港回归纪念日"},
            {"8-1","建军节","八一建党节","81建党节"},
            {"5-10","母亲节"},
            {"6-21","父亲节"},
            {"9-3","抗战纪念日","抗战胜利纪念日"},
            {"3-12","植树节","植树日"},
            {"3-22","节水节","节水日"},
            {"4-1","愚人节"},
            {"10-16","世界粮食日"},
            {"12-26","毛泽东纪念日","毛泽东诞辰纪念日"},
            {"3-5","周恩来纪念日","周恩来诞辰纪念日"},
            {"12-13","南京大屠杀纪念日"},
            {"12-25","耶诞节","圣诞节"},
            {"12-24","平安夜"},
            {"1-1","元旦","元旦节"}
    };

    private final  String[][] LUNAR_FESTIVAL_WORDS = {
            {"1-1","春节","正月初一"},
            {"1-15","元宵节","正月十五"},
            {"5-5","端午节","五月初五"},
            {"7-7","七夕","七夕女儿节"},
            {"7-14","中元节","鬼节"},
            {"8-15","中秋节"},
            {"2-2","龙抬头节"},
            {"2-2","七夕女儿节"},
            {"9-9","重阳节"},
            {"12-21","冬至"},
            {"12-8","腊八节","腊月二十三","小年"},
            {"1^1-1","除夕"}//表示1月初1向前推进1天， 1-1^2向后推进2天

    };

    public static  FestivalFilter getInstance(){
        if(instance==null){
            instance = new FestivalFilter();
        }
        return instance;
    }

    public List<DateTimeNode>  getFilterDateNodes(String sourceText)  {
        List<DateTimeNode> dateTimeNodes = new ArrayList<>();
        if(TextUtils.isEmpty(sourceText)) return dateTimeNodes;
        DateTimeNode yearNode = DateTimeHelper.tryGetYearNode(sourceText);

        for (int i=0;i<COMMON_FESTEVL_WORDS.length;i++){
            String[] festvalNames = COMMON_FESTEVL_WORDS[i];
            if(festvalNames==null) continue;

            String festvalDate = festvalNames[0];

            for (int j=1;j<festvalNames.length;j++){
                String festvalName = festvalNames[j];
                if(!sourceText.contains(festvalName))  continue;

                String locatorText = "";
                String resultText  = festvalDate;
                if(yearNode.index>=0){
                    locatorText = yearNode.text;
                    resultText = String.format("%s-%s",yearNode.resultText,festvalDate);
                }
                DateTimeNode dateTimeNode = new DateTimeNode();
                dateTimeNode.text = festvalName;
                dateTimeNode.locatorText = locatorText;
                dateTimeNode.index = sourceText.lastIndexOf(festvalName);
                dateTimeNode.resultText = resultText;

                dateTimeNodes.add(dateTimeNode);
            }
        }

        for (int i=0;i<LUNAR_FESTIVAL_WORDS.length;i++){
            String[] festvalNames = LUNAR_FESTIVAL_WORDS[i];
            for (int j=1;j<festvalNames.length;j++){
                String festvalName = festvalNames[j];
                if(!sourceText.contains(festvalName))  continue;
                String locatorText = "";
                String date = chineseFestivalToSolarDate(yearNode.resultText,festvalNames[0]);

                String resultText  = date;
                if(yearNode.index>=0){
                    locatorText = yearNode.text;
                }
                if(TextUtils.isEmpty(date)) continue;

                DateTimeNode dateTimeNode = new DateTimeNode();
                dateTimeNode.text = festvalName;
                dateTimeNode.locatorText = locatorText;
                dateTimeNode.index = sourceText.lastIndexOf(festvalName);
                dateTimeNode.resultText = resultText;
                dateTimeNodes.add(dateTimeNode);
            }
        }

        DateTimeNode dateTimeNode = handleQMFestival(yearNode,sourceText);
        if(dateTimeNode!=null){
            dateTimeNodes.add(dateTimeNode);
        }

        if(dateTimeNodes!=null){
            Collections.sort(dateTimeNodes);
        }

        return dateTimeNodes;
    }

    private DateTimeNode handleQMFestival(DateTimeNode yearNode,String sourceText) {
        if(!sourceText.contains(QM_FESTIVAL)){
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        SDF.applyPattern("MM-dd");
        int targetYear = calendar.get(Calendar.YEAR);
        boolean hasDeclareYearNode = (yearNode!=null && yearNode.index!=-1);
        if(hasDeclareYearNode){
            targetYear = DateTimeHelper.getIntegerValue(yearNode.resultText);
        }

        String TODAY = SDF.format(calendar.getTime());
        String QM = getQMFestival(targetYear);

        Date QMDate = null;
        try {
            QMDate = SDF.parse(QM);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        if(QMDate==null) return null;

        Calendar target = Calendar.getInstance();
        target.setTimeInMillis(QMDate.getTime());

        if(hasDeclareYearNode==false&& TODAY.compareTo(QM)>0){
            calendar.add(Calendar.YEAR,1);
        }
        calendar.set(Calendar.DAY_OF_MONTH,target.get(Calendar.DAY_OF_MONTH));
        calendar.set(Calendar.MONTH,target.get(Calendar.MONTH));

        SDF.applyPattern("yyyy-MM-dd");

        DateTimeNode dateTimeNode = new DateTimeNode();
        dateTimeNode.text = QM_FESTIVAL;
        dateTimeNode.locatorText = hasDeclareYearNode?yearNode.text:"";
        dateTimeNode.index = sourceText.lastIndexOf(QM_FESTIVAL);
        dateTimeNode.resultText = SDF.format(calendar.getTime());

        return dateTimeNode;
    }
    private String getQMFestival(int fullYear) {
        //清明节的日期是不固定的，规律是：闰年开始的前2年是4月4日，闰年开始的第3年和第4年是4月5日
        if(DateTimeHelper.isLeapYear(fullYear) || DateTimeHelper.isLeapYear(fullYear -1)){
            return "04-04";
        }
        else{
            return "04-05";
        }
    }

    private static String chineseFestivalToSolarDate(String yearNumber,String chineseDate) {
        if( TextUtils.isEmpty(chineseDate)) return TextPattern.WORD_EMPTY;
        int dx = 0;
        String date = "";
        if(chineseDate.contains("^")){
            String[]  phases = chineseDate.split("\\^");
            if(TextUtils.isDigitsOnly(phases[0])){
                dx = -DateTimeHelper.getIntegerValue(phases[0]);
                date =phases[1];
            }else{
                date =phases[0];
                dx = DateTimeHelper.getIntegerValue(phases[1]);
            }
        }else{
            date = chineseDate;
        }
        int targetYear = -1;
        if(!TextUtils.isEmpty(yearNumber)){
            targetYear = DateTimeHelper.getIntegerValue(yearNumber);
        }
        int targetMonth = DateTimeHelper.getIntegerValue(DateTimeHelper.readPrevNumberAtFlag(date,"-"));
        int targetDay =  DateTimeHelper.getIntegerValue(DateTimeHelper.readNextNumberAtFlag(date,"-"));

        SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        int  year = calendar.get(Calendar.YEAR);
        int  month = calendar.get(Calendar.MONTH) +1;
        int  day = calendar.get(Calendar.DAY_OF_MONTH);

        int d=day;
        int m = month;
        int maxMonth = 24;

        if (targetYear > 0) {
            //具有确切的年份，因此只在本年度推算，最大可以跨2月 12+2
            m = 1;
            year = targetYear;
            maxMonth = 14;

            calendar.set(Calendar.YEAR,targetMonth);
        }
        for (;m<maxMonth;m++) {
            for (;d<31;d++) {
                int _maskMonth = m%12;
                if(_maskMonth==0){
                    _maskMonth=12;
                }
                LunarCalendarUtils.Solar solar = new LunarCalendarUtils.Solar(year, _maskMonth, d);
                LunarCalendarUtils.Lunar lunar = LunarCalendarUtils.solarToLunar(solar);

                if(lunar==null) continue;
                if(lunar.lunarMonth==targetMonth && lunar.lunarDay==targetDay){
                    calendar.set(year, _maskMonth-1, d);
                    calendar.add(Calendar.DAY_OF_YEAR,dx);
                    return SDF.format(calendar.getTime());
                }
            }
            d=0;
            if(targetYear==-1 && m%12==0){
                year++;
            }
        }
        return TextPattern.WORD_EMPTY;
    }

}
